import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import axios from 'axios'
import { ContentTypeEnum, RequestEnum } from '../enums/http-enum'
import { ElMessage } from 'element-plus'
import store from '@/store'
 
export interface ResponseBody<T = any> {
  code: number
  data?: T
  msg: string
  status: number
}

export interface RequestConfigExtra {
  token?: boolean
  customDev?: boolean
  loading?: boolean
}
const instance: AxiosInstance = axios.create({
  baseURL: process.env.VUE_APP_BASE_URL,
  timeout: 60000,
  headers: { 'Content-Type': ContentTypeEnum.JSON },
})


export function setToken(token: string){
  localStorage.setItem('token',token)
}

export function removeToken(key:string){
  localStorage.removeItem(key)
}


 async function requestHandler(config: InternalAxiosRequestConfig & RequestConfigExtra): Promise<InternalAxiosRequestConfig> {
   config.baseURL =process.env.VUE_APP_BASE_URL
  const token = store.getters.getToken
  if (token  && config.token !== false)
     config.headers.Authorization = token
  return config
}
 
function responseHandler(response: any): ResponseBody<any> | AxiosResponse<any> | Promise<any> | any {
   
 
    if (response.data instanceof Blob) {
      return response
    } 
   
    return response.data
  


  
}

function errorHandler(error: any): Promise<any> {
  if (error.response) {
    const { data } = error.response
    ElMessage.error(data.msg)
    return Promise.reject(error)
  }
  return Promise.reject(error)
}
interface AxiosOptions<T> {
  url: string
  params?: T
  data?: T
}
instance.interceptors.request.use(requestHandler)

instance.interceptors.response.use(responseHandler, errorHandler)

export default instance
function instancePromise<R = any, T = any>(options: AxiosOptions<T> & RequestConfigExtra): Promise<ResponseBody<R>> {
   return new Promise((resolve, reject) => {
    instance.request(options).then((res) => {
      resolve(res as any)
    }).catch((e: Error | AxiosError) => {
      reject(e)
    })

  })
}
export function useGet< R = any, T = any>(url: string, params?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<ResponseBody<R>> {
  const options = {
    url,
    params,
    method: RequestEnum.GET,
    ...config,
  }
  return instancePromise< R, T >(options)
}

export function usePost< R = any, T = any>(url: string, data?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<ResponseBody<R>> {
  const options = {
    url,
    data,
    method: RequestEnum.POST,
    ...config,
  }
  return instancePromise< R, T >(options)
}

export function usePut< R = any, T = any>(url: string, data?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<ResponseBody<R>> {
  const options = {
    url,
    data,
    method: RequestEnum.PUT,
    ...config,
  }
  return instancePromise<R, T>(options)
}

export function useDelete< R = any, T = any>(url: string, data?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<ResponseBody<R>> {
  const options = {
    url,
    data,
    method: RequestEnum.DELETE,
    ...config,
  }
  return instancePromise<R, T>(options)
}
